/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { computed, ref, Ref, SetupContext, watch } from 'vue';
import { ButtonEditProps } from '../button-edit.props';
import { UsePopup, UseTextBox } from './types';

export function useTextBox(
    props: ButtonEditProps,
    context: SetupContext,
    modelValue: Ref<string>,
    displayText: Ref<string>,
    usePopupComposition: UsePopup
): UseTextBox {
    const shouldPopupOnInput = ref(props.popupOnInput);
    const shouldPopupOnFocus = ref(props.popupOnFocus);
    const { shouldPopupContent } = usePopupComposition;

    const textBoxTitle = computed(() => (props.enableTitle ? modelValue.value : ''));

    const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));

    const isTextBoxReadonly = computed(() => props.readonly || !props.editable);

    let focusState = false;

    const hasFocusedTextBox = computed(() => !props.disable && focusState);

    const textBoxClass = computed(() => ({
        'text-left': props.textAlign === 'left',
        'text-center': props.textAlign === 'center',
        'text-right': props.textAlign === 'right',
        'form-control': true,
        'f-utils-fill': true
    }));

    const inputGroupClass = computed(() => {
        const classObject = {
            'input-group': true,
            'f-state-disable': props.disable,
            'f-state-editable': props.editable && !props.disable && !props.readonly,
            'f-state-readonly': props.readonly && !props.disable,
            'f-state-focus': hasFocusedTextBox.value
        };
        return classObject;
    });

    function changeTextBoxValue(newValue: string, shouldEmitChangeEvent = true) {
        if (modelValue.value !== newValue) {
            modelValue.value = newValue;
            if (shouldEmitChangeEvent) {
                context.emit('change', newValue);
            }
            context.emit('update:modelValue', newValue);
        }
    }

    function commitValue(value: any) {
        shouldPopupContent.value = false;
        changeTextBoxValue(value, true);
    }

    watch(
        () => props.modelValue,
        (value: string) => {
            modelValue.value = value;
            context.emit('change', value);
        }
    );

    function onBlurTextBox($event: Event) {
        focusState = false;
        context.emit('blur', $event);
        $event.stopPropagation();
    }

    function onClickTextBox($event: Event) {
        context.emit('click', $event);
    }

    function onFocusTextBox($event: Event) {
        if (props.disable) {
            focusState = true;
            return;
        }
        focusState = true;
        if (!isTextBoxReadonly.value) {
            context.emit('focus', $event);
            if (shouldPopupOnFocus.value && !shouldPopupContent.value) {
                usePopupComposition.popup();
            }
        }
    }

    function onInput($event: Event) {
        context.emit('input', ($event.target as HTMLInputElement).value);
        const newValue = ($event.target as HTMLInputElement).value;
        displayText.value = newValue;
        if (modelValue.value !== newValue) {
            changeTextBoxValue(newValue, false);
            // context.emit('update:modelValue', ($event.target as HTMLInputElement).value);
        }
        if (shouldPopupOnInput.value && !shouldPopupContent.value) {
            usePopupComposition.popup();
        }
    }

    function onMouseDownTextBox($event: MouseEvent) {
        const target = $event.target as any;
        if (target.tagName !== 'INPUT') {
            $event.preventDefault();
        }
        $event.stopPropagation();
    }

    function onKeyDownTextBox($event: Event) {
        context.emit('keydown', $event);
    }

    function onKeyUpTextBox($event: KeyboardEvent) {
        if ($event.key === 'Enter' && (shouldPopupOnInput.value || shouldPopupOnFocus.value)) {
            usePopupComposition.hidePopup();
        }
        context.emit('keyup', $event);
    }

    function onTextBoxValueChange($event: Event) {
        const newValue = ($event.target as HTMLInputElement).value;
        $event.stopPropagation();
        changeTextBoxValue(newValue);
    }

    return {
        hasFocusedTextBox,
        isTextBoxReadonly,
        textBoxClass,
        textBoxPlaceholder,
        textBoxTitle,
        inputGroupClass,
        changeTextBoxValue,
        commitValue,
        onBlurTextBox,
        onClickTextBox,
        onFocusTextBox,
        onInput,
        onKeyDownTextBox,
        onKeyUpTextBox,
        onMouseDownTextBox,
        onTextBoxValueChange
    };
}
